home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 726-750 / 741 / rkrm_devices / rkrm_devices.lha / Console / Console.c < prev   
C/C++ Source or Header  |  1992-09-03  |  14KB  |  401 lines

  1. /*
  2.  * Copyright (c) 1992 Commodore-Amiga, Inc.
  3.  * 
  4.  * This example is provided in electronic form by Commodore-Amiga, Inc. for 
  5.  * use with the "Amiga ROM Kernel Reference Manual: Devices", 3rd Edition, 
  6.  * published by Addison-Wesley (ISBN 0-201-56775-X).
  7.  * 
  8.  * The "Amiga ROM Kernel Reference Manual: Devices" contains additional 
  9.  * information on the correct usage of the techniques and operating system 
  10.  * functions presented in these examples.  The source and executable code 
  11.  * of these examples may only be distributed in free electronic form, via 
  12.  * bulletin board or as part of a fully non-commercial and freely 
  13.  * redistributable diskette.  Both the source and executable code (including 
  14.  * comments) must be included, without modification, in any copy.  This 
  15.  * example may not be published in printed form or distributed with any
  16.  * commercial product.  However, the programming techniques and support
  17.  * routines set forth in these examples may be used in the development
  18.  * of original executable software products for Commodore Amiga computers.
  19.  * 
  20.  * All other rights reserved.
  21.  * 
  22.  * This example is provided "as-is" and is subject to change; no
  23.  * warranties are made.  All use is at your own risk. No liability or
  24.  * responsibility is assumed.
  25.  *
  26.  *************************************************************************
  27.  *
  28.  * Console.c
  29.  *
  30.  * Example of opening a window and using the console device
  31.  * to send text and control sequences to it.  The example can be
  32.  * easily modified to do additional control sequences.
  33.  *
  34.  * Compile with SAS C 5.10: LC -b1 -cfistq -v -y -L
  35.  *
  36.  * Run from CLI only.
  37.  */
  38.  
  39. #include <exec/types.h>
  40. #include <exec/io.h>
  41. #include <exec/memory.h>
  42. #include <intuition/intuition.h>
  43. #include <dos/dos.h>
  44. #include <devices/console.h>
  45.  
  46. #include <clib/exec_protos.h>
  47. #include <clib/alib_protos.h>
  48. #include <clib/dos_protos.h>
  49. #include <clib/intuition_protos.h>
  50.  
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53.  
  54. #ifdef LATTICE
  55. int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */
  56. int chkabort(void) { return(0); }  /* really */
  57. #endif
  58.  
  59.  
  60. /* Note - using two character <CSI> ESC[.  Hex 9B could be used instead */
  61. #define RESETCON  "\033c"
  62. #define CURSOFF   "\033[0 p"
  63. #define CURSON    "\033[ p"
  64. #define DELCHAR   "\033[P"
  65.  
  66. /* SGR (set graphic rendition) */
  67. #define COLOR02   "\033[32m"
  68. #define COLOR03   "\033[33m"
  69. #define ITALICS   "\033[3m"
  70. #define BOLD      "\033[1m"
  71. #define UNDERLINE "\033[4m"
  72. #define NORMAL    "\033[0m"
  73.  
  74.  
  75. /* our functions */
  76. void cleanexit(UBYTE *,LONG);
  77. void cleanup(void);
  78. BYTE OpenConsole(struct IOStdReq *,struct IOStdReq *, struct Window *);
  79. void CloseConsole(struct IOStdReq *);
  80. void QueueRead(struct IOStdReq *, UBYTE *);
  81. UBYTE ConGetChar(struct MsgPort *, UBYTE *);
  82. LONG ConMayGetChar(struct MsgPort *, UBYTE *);
  83. void ConPuts(struct IOStdReq *, UBYTE *);
  84. void ConWrite(struct IOStdReq *, UBYTE *, LONG);
  85. void ConPutChar(struct IOStdReq *, UBYTE);
  86. void main(int argc, char **argv);
  87. struct NewWindow nw =
  88.     {
  89.     10, 10,                           /* starting position (left,top) */
  90.     620,180,                          /* width, height */
  91.     -1,-1,                            /* detailpen, blockpen */
  92.     CLOSEWINDOW,                      /* flags for idcmp */
  93.     WINDOWDEPTH|WINDOWSIZING|
  94.     WINDOWDRAG|WINDOWCLOSE|
  95.     SMART_REFRESH|ACTIVATE,           /* window flags */
  96.     NULL,                             /* no user gadgets */
  97.     NULL,                             /* no user checkmark */
  98.     "Console Test",                   /* title */
  99.     NULL,                             /* pointer to window screen */
  100.     NULL,                             /* pointer to super bitmap */
  101.     100,45,                           /* min width, height */
  102.     640,200,                          /* max width, height */
  103.     WBENCHSCREEN                      /* open on workbench screen */
  104.     };
  105.  
  106.  
  107. /* Opens/allocations we'll need to clean up */
  108. struct Library  *IntuitionBase = NULL;
  109. struct Window   *win = NULL;
  110. struct IOStdReq *writeReq = NULL;    /* I/O request block pointer */
  111. struct MsgPort  *writePort = NULL;   /* replyport for writes      */
  112. struct IOStdReq *readReq = NULL;     /* I/O request block pointer */
  113. struct MsgPort  *readPort = NULL;    /* replyport for reads       */
  114. BOOL OpenedConsole = FALSE;
  115.  
  116. BOOL FromWb;
  117.  
  118. void main(argc, argv)
  119. int argc;
  120. char **argv;
  121.     {
  122.     struct IntuiMessage *winmsg;
  123.     ULONG signals, conreadsig, windowsig;
  124.     LONG lch;
  125.     SHORT InControl = 0;
  126.     BOOL Done = FALSE;
  127.     UBYTE ch, ibuf;
  128.     UBYTE obuf[200];
  129.     BYTE error;
  130.  
  131.     FromWb = (argc==0L) ? TRUE : FALSE;
  132.  
  133.     if(!(IntuitionBase=OpenLibrary("intuition.library",0)))
  134.          cleanexit("Can't open intuition\n",RETURN_FAIL);
  135.  
  136.     /* Create reply port and io block for writing to console */
  137.     if(!(writePort = CreatePort("RKM.console.write",0)))
  138.          cleanexit("Can't create write port\n",RETURN_FAIL);
  139.  
  140.     if(!(writeReq = (struct IOStdReq *)
  141.                     CreateExtIO(writePort,(LONG)sizeof(struct IOStdReq))))
  142.          cleanexit("Can't create write request\n",RETURN_FAIL);
  143.  
  144.     /* Create reply port and io block for reading from console */
  145.     if(!(readPort = CreatePort("RKM.console.read",0)))
  146.          cleanexit("Can't create read port\n",RETURN_FAIL);
  147.  
  148.     if(!(readReq = (struct IOStdReq *)
  149.                    CreateExtIO(readPort,(LONG)sizeof(struct IOStdReq))))
  150.          cleanexit("Can't create read request\n",RETURN_FAIL);
  151.  
  152.     /* Open a window */
  153.     if(!(win = OpenWindow(&nw)))
  154.          cleanexit("Can't open window\n",RETURN_FAIL);
  155.  
  156.     /* Now, attach a console to the window */
  157.     if(error = OpenConsole(writeReq,readReq,win))
  158.          cleanexit("Can't open console.device\n",RETURN_FAIL);
  159.     else OpenedConsole = TRUE;
  160.  
  161.     /* Demonstrate some console escape sequences */
  162.     ConPuts(writeReq,"Here's some normal text\n");
  163.     sprintf(obuf,"%s%sHere's text in color 3 and italics\n",COLOR03,ITALICS);
  164.     ConPuts(writeReq,obuf);
  165.     ConPuts(writeReq,NORMAL);
  166.     Delay(50);      /* Delay for dramatic demo effect */
  167.     ConPuts(writeReq,"We will now delete this asterisk =*=");
  168.     Delay(50);
  169.     ConPuts(writeReq,"\b\b");  /* backspace twice */
  170.     Delay(50);
  171.     ConPuts(writeReq,DELCHAR); /* delete the character */
  172.     Delay(50);
  173.  
  174.     QueueRead(readReq,&ibuf); /* send the first console read request */
  175.  
  176.     ConPuts(writeReq,"\n\nNow reading console\n");
  177.     ConPuts(writeReq,"Type some keys.  Close window when done.\n\n");
  178.  
  179.     conreadsig = 1 << readPort->mp_SigBit;
  180.     windowsig = 1 << win->UserPort->mp_SigBit;
  181.  
  182.     while(!Done)
  183.         {
  184.         /* A character, or an IDCMP msg, or both could wake us up */
  185.         signals = Wait(conreadsig|windowsig);
  186.  
  187.         /* If a console signal was received, get the character */
  188.         if (signals & conreadsig)
  189.             {
  190.             if((lch = ConMayGetChar(readPort,&ibuf)) != -1)
  191.                 {
  192.                 ch = lch;
  193.                 /* Show hex and ascii (if printable) for char we got.
  194.                  * If you want to parse received control sequences, such as
  195.                  * function or Help keys, you would buffer control sequences
  196.                  * as you receive them, starting to buffer whenever you
  197.                  * receive 0x9B (or 0x1B[ for user-typed sequences) and
  198.                  * ending when you receive a valid terminating character
  199.                  * for the type of control sequence you are receiving.
  200.                  * For CSI sequences, valid terminating characters
  201.                  * are generally 0x40 through 0x7E.
  202.                  * In our example, InControl has the following values:
  203.                  * 0 = no, 1 = have 0x1B, 2 = have 0x9B OR 0x1B and [,
  204.                  * 3 = now inside control sequence, -1 = normal end esc,
  205.                  * -2 = non-CSI(no [) 0x1B end esc
  206.                  * NOTE - a more complex parser is required to recognize
  207.                  *  other types of control sequences.
  208.                  */
  209.  
  210.                 /* 0x1B ESC not followed by '[', is not CSI seq */
  211.                 if (InControl==1)
  212.                     {
  213.                     if(ch=='[') InControl = 2;
  214.                     else InControl = -2;
  215.                     }
  216.  
  217.                 if ((ch==0x9B)||(ch==0x1B))  /* Control seq starting */
  218.                     {
  219.                     InControl = (ch==0x1B) ? 1 : 2;
  220.                     ConPuts(writeReq,"=== Control Seq ===\n");
  221.                     }
  222.  
  223.                 /* We'll show value of this char we received */
  224.                 if (((ch >= 0x1F)&&(ch <= 0x7E))||(ch >= 0xA0))
  225.                    sprintf(obuf,"Received: hex %02x = %c\n",ch,ch);
  226.                 else sprintf(obuf,"Received: hex %02x\n",ch);
  227.                 ConPuts(writeReq,obuf);
  228.  
  229.                 /* Valid ESC sequence terminator ends an ESC seq */
  230.                 if ((InControl==3)&&((ch >= 0x40) && (ch <= 0x7E)))
  231.                     {
  232.                     InControl = -1;
  233.                     }
  234.                 if (InControl==2) InControl = 3;
  235.                 /* ESC sequence finished (-1 if OK, -2 if bogus) */
  236.                 if (InControl < 0)
  237.                     {
  238.                     InControl = 0;
  239.                     ConPuts(writeReq,"=== End Control ===\n");
  240.                     }
  241.                 }
  242.             }
  243.  
  244.         /* If IDCMP messages received, handle them */
  245.         if (signals & windowsig)
  246.             {
  247.             /* We have to ReplyMsg these when done with them */
  248.             while (winmsg = (struct IntuiMessage *)GetMsg(win->UserPort))
  249.                 {
  250.                 switch(winmsg->Class)
  251.                     {
  252.                     case CLOSEWINDOW:
  253.                       Done = TRUE;
  254.                       break;
  255.                     default:
  256.                       break;
  257.                      }
  258.                 ReplyMsg((struct Message *)winmsg);
  259.                 }
  260.             }
  261.         }
  262.  
  263.     /* We always have an outstanding queued read request
  264.      * so we must abort it if it hasn't completed,
  265.      * and we must remove it.
  266.      */
  267.     if(!(CheckIO(readReq)))  AbortIO(readReq);
  268.     WaitIO(readReq);     /* clear it from our replyport */
  269.  
  270.     cleanup();
  271.     exit(RETURN_OK);
  272.     }
  273.  
  274. void cleanexit(UBYTE *s,LONG n)
  275.     {
  276.     if(*s & (!FromWb)) printf(s);
  277.     cleanup();
  278.     exit(n);
  279.     }
  280.  
  281. void cleanup()
  282.     {
  283.     if(OpenedConsole)
  284.        CloseConsole(writeReq);
  285.     if(win)
  286.        CloseWindow(win);
  287.     if(readReq)
  288.        DeleteExtIO(readReq);
  289.     if(readPort)
  290.        DeletePort(readPort);
  291.     if(writeReq)
  292.        DeleteExtIO(writeReq);
  293.     if(writePort)
  294.        DeletePort(writePort);
  295.     if(IntuitionBase)
  296.        CloseLibrary(IntuitionBase);
  297.     }
  298.  
  299.  
  300. /* Attach console device to an open Intuition window.
  301.  * This function returns a value of 0 if the console
  302.  * device opened correctly and a nonzero value (the error
  303.  * returned from OpenDevice) if there was an error.
  304.  */
  305. BYTE OpenConsole(writereq, readreq, window)
  306. struct IOStdReq *writereq;
  307. struct IOStdReq *readreq;
  308. struct Window *window;
  309.     {
  310.     BYTE error;
  311.  
  312.     writereq->io_Data = (APTR) window;
  313.     writereq->io_Length = sizeof(struct Window);
  314.     error = OpenDevice("console.device", 0, writereq, 0);
  315.     readreq->io_Device = writereq->io_Device; /* clone required parts */
  316.     readreq->io_Unit   = writereq->io_Unit;
  317.     return(error);
  318.     }
  319.  
  320. void CloseConsole(struct IOStdReq *writereq)
  321.     {
  322.     CloseDevice(writereq);
  323.     }
  324.  
  325. /* Output a single character to a specified console
  326.  */
  327. void ConPutChar(struct IOStdReq *writereq, UBYTE character)
  328.     {
  329.     writereq->io_Command = CMD_WRITE;
  330.     writereq->io_Data = (APTR)&character;
  331.     writereq->io_Length = 1;
  332.     DoIO(writereq);
  333.     /* command works because DoIO blocks until command is done
  334.      * (otherwise ptr to the character could become invalid)
  335.      */
  336.     }
  337.  
  338.  
  339. /* Output a stream of known length to a console
  340.  */
  341. void ConWrite(struct IOStdReq *writereq, UBYTE *string, LONG length)
  342.     {
  343.     writereq->io_Command = CMD_WRITE;
  344.     writereq->io_Data = (APTR)string;
  345.     writereq->io_Length = length;
  346.     DoIO(writereq);
  347.     /* command works because DoIO blocks until command is done
  348.      * (otherwise ptr to string could become invalid in the meantime)
  349.      */
  350.     }
  351.  
  352.  
  353. /* Output a NULL-terminated string of characters to a console
  354.  */
  355. void ConPuts(struct IOStdReq *writereq,UBYTE *string)
  356.     {
  357.     writereq->io_Command = CMD_WRITE;
  358.     writereq->io_Data = (APTR)string;
  359.     writereq->io_Length = -1;  /* means print till terminating null */
  360.     DoIO(writereq);
  361.     }
  362.  
  363. /* Queue up a read request to console, passing it pointer
  364.  * to a buffer into which it can read the character
  365.  */
  366. void QueueRead(struct IOStdReq *readreq, UBYTE *whereto)
  367.    {
  368.    readreq->io_Command = CMD_READ;
  369.    readreq->io_Data = (APTR)whereto;
  370.    readreq->io_Length = 1;
  371.    SendIO(readreq);
  372.    }
  373.  
  374. /* Check if a character has been received.
  375.  * If none, return -1
  376.  */
  377. LONG ConMayGetChar(struct MsgPort *msgport, UBYTE *whereto)
  378.     {
  379.     register temp;
  380.     struct IOStdReq *readreq;
  381.  
  382.     if (!(readreq = (struct IOStdReq *)GetMsg(msgport))) return(-1);
  383.     temp = *whereto;                /* get the character */
  384.     QueueRead(readreq,whereto);     /* then re-use the request block */
  385.     return(temp);
  386.     }
  387.  
  388. /* Wait for a character
  389.  */
  390. UBYTE ConGetChar(struct MsgPort *msgport, UBYTE *whereto)
  391.     {
  392.     register temp;
  393.     struct IOStdReq *readreq;
  394.  
  395.     WaitPort(msgport);
  396.     readreq = (struct IOStdReq *)GetMsg(msgport);
  397.     temp = *whereto;               /* get the character */
  398.     QueueRead(readreq,whereto);    /* then re-use the request block*/
  399.     return((UBYTE)temp);
  400.     }
  401.